package api

import (
	"encoding/json"
	"fmt"
)

type WebError struct {
	Code int
	Msg  string
}

func (e WebError) Error() string {
	return fmt.Sprintf("[%v] %v", e.Code, e.Msg)
}

func (e WebError) Cause(err error) error {
	return WebError{
		Code: e.Code,
		Msg:  fmt.Sprintf("%v: %v", e.Msg, err.Error()),
	}
}

type RspBody struct {
	Code int         `json:"code"`
	Data interface{} `json:"data,omitempty"`
	Msg  string      `json:"msg"`
}

func Rsp(data interface{}, err error) RspBody {
	var rsp RspBody
	rsp.Data = data
	if err != nil {
		if cgierr, ok := err.(WebError); ok {
			rsp.Code = cgierr.Code
			rsp.Msg = cgierr.Msg
		} else {
			rsp.Code = 10000 // 未定义错误
			rsp.Msg = err.Error()
		}
	}
	return rsp
}

func RspBuf(data interface{}, err error) []byte {
	rspbody := Rsp(data, err)
	buf, err := json.Marshal(rspbody)
	if err != nil {
		return []byte(fmt.Sprintf(`{"code":-1,"msg":"marshal rsp err, %v"}`, err))
	}
	return buf
}

// data 必须是指针
func ReadRsp(rspbuf []byte, data interface{}) error {
	var rsp struct {
		Code int             `json:"code"`
		Data json.RawMessage `json:"data,omitempty"`
		Msg  string          `json:"msg"`
	}
	if err := json.Unmarshal(rspbuf, &rsp); err != nil {
		return err
	}

	if rsp.Code != 0 {
		return WebError{
			Code: rsp.Code,
			Msg:  rsp.Msg,
		}
	}

	if data != nil {
		if err := json.Unmarshal(rsp.Data, data); err != nil {
			return err
		}
	}

	return nil
}
